// rmenu.c
#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef __linux__
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h> // 新增：解决open函数和O_RDWR定义问题
#endif
// 配置
#define WIDTH 800
#define HEIGHT 600
#define PADDING 15
#define FONT_SIZE 50
#define MAX_ITEMS 4000
#define MAX_INPUT_LEN 256
#define MAX_VISIBLE 10
#define SYSTEM_FONT_PATH "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"

// 全局状态
typedef struct
{
    char text[256];
    bool is_match;
} MenuItem;

MenuItem items[MAX_ITEMS];
int item_count = 0;
char input_str[MAX_INPUT_LEN] = "";
int selected_idx = 0;
int scroll_offset = 0;
bool running = true;
size_t cursor = 0;
Font app_font;
Font default_font;
pid_t child_pid = -1;
bool command_executing = false;
bool window_should_close = false;

// 辅助函数：获取文件名
const char *get_basename(const char *path)
{
    const char *slash = strrchr(path, '/');
    return (slash) ? (slash + 1) : path;
}

// 读取标准输入项目
void read_items_from_stdin()
{
    char buf[512];
    item_count = 0;
    while (running && item_count < MAX_ITEMS)
    {
        ssize_t read_len = read(STDIN_FILENO, buf, sizeof(buf) - 1);
        if (read_len <= 0)
        {
            if (read_len < 0 && errno == EINTR)
                continue;
            break;
        }

        buf[read_len] = '\0';
        char *line = strtok(buf, "\n");
        while (line != NULL && item_count < MAX_ITEMS)
        {
            size_t len = strlen(line);
            while (len > 0 && isspace((unsigned char)line[len - 1]))
                line[--len] = '\0';

            if (len > 0)
            {
                strncpy(items[item_count].text, line, sizeof(items[item_count].text) - 1);
                items[item_count].text[sizeof(items[item_count].text) - 1] = '\0';
                items[item_count].is_match = true;
                item_count++;
            }
            line = strtok(NULL, "\n");
        }
    }
}

// 过滤项目
void filter_items()
{
    int input_len = strlen(input_str);
    if (input_len == 0)
    {
        for (int i = 0; i < item_count; i++)
            items[i].is_match = true;
        selected_idx = (item_count > 0) ? 0 : -1;
        scroll_offset = 0;
        return;
    }

    int match_count = 0;
    int first_match_idx = -1;
    for (int i = 0; i < item_count; i++)
    {
        const char *basename = get_basename(items[i].text);
        int basename_len = strlen(basename);
        bool match = (basename_len >= input_len);

        if (match)
        {
            for (int j = 0; j < input_len; j++)
            {
                if (tolower((unsigned char)input_str[j]) != tolower((unsigned char)basename[j]))
                {
                    match = false;
                    break;
                }
            }
        }

        items[i].is_match = match;
        if (match)
        {
            match_count++;
            if (first_match_idx == -1)
                first_match_idx = i;
        }
    }

    selected_idx = (match_count == 0) ? -1 : first_match_idx;
    int center_pos = MAX_VISIBLE / 2;
    scroll_offset = selected_idx - center_pos;
    if (scroll_offset < 0)
        scroll_offset = 0;
}

// 非阻塞检查子进程状态
void check_child_process()
{
    if (child_pid == -1)
        return;

    int status;
    pid_t result = waitpid(child_pid, &status, WNOHANG);
    if (result == child_pid || result == -1)
    {
        child_pid = -1;
        command_executing = false;
        window_should_close = true;
    }
}

// 命令执行逻辑（修复编译错误）
void execute_command(const char *cmd)
{
    if (!cmd || strlen(cmd) == 0 || command_executing)
        return;

    // 禁用信号干扰
    sigset_t mask, old_mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &mask, &old_mask);

    pid_t pid = fork();
    if (pid == -1)
    {
        perror("fork failed");
        sigprocmask(SIG_SETMASK, &old_mask, NULL);
        return;
    }

    if (pid == 0)
    {
        // 子进程：重置信号掩码，脱离终端，执行命令
        sigprocmask(SIG_SETMASK, &old_mask, NULL);

        // 重定向标准输入输出到/dev/null（修复编译错误：已包含fcntl.h）
        int null_fd = open("/dev/null", O_RDWR);
        if (null_fd != -1)
        {
            dup2(null_fd, STDIN_FILENO);
            dup2(null_fd, STDOUT_FILENO);
            dup2(null_fd, STDERR_FILENO);
            if (null_fd > 2)
                close(null_fd);
        }

        // 拆分命令为参数数组
        char *args[64];
        int arg_idx = 0;
        char *token = strtok((char *)cmd, " ");
        while (token != NULL && arg_idx < 63)
        {
            args[arg_idx++] = token;
            token = strtok(NULL, " ");
        }
        args[arg_idx] = NULL;

        // 执行命令
        execvp(args[0], args);
        exit(EXIT_FAILURE);
    }
    else
    {
        // 父进程：记录子进程ID，标记命令执行中
        child_pid = pid;
        command_executing = true;
        sigprocmask(SIG_SETMASK, &old_mask, NULL);
    }
}

// 输入处理
void handle_input()
{
    if (command_executing)
        return;

    bool ctrl_pressed = IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL);

    if (IsKeyPressed(KEY_ESCAPE) || window_should_close)
    {
        running = false;
        return;
    }

    // 鼠标滚轮导航
    float wheel_move = GetMouseWheelMove();
    if (wheel_move != 0 && selected_idx != -1)
    {
        int center_pos = MAX_VISIBLE / 2;
        if (wheel_move > 0)
        {
            int prev_idx = selected_idx - 1;
            while (prev_idx >= 0 && !items[prev_idx].is_match)
                prev_idx--;
            if (prev_idx >= 0)
            {
                selected_idx = prev_idx;
                scroll_offset = selected_idx - center_pos;
                scroll_offset = (scroll_offset < 0) ? 0 : scroll_offset;
            }
        }
        else
        {
            int next_idx = selected_idx + 1;
            while (next_idx < item_count && !items[next_idx].is_match)
                next_idx++;
            if (next_idx < item_count)
            {
                selected_idx = next_idx;
                scroll_offset = selected_idx - center_pos;
                scroll_offset = (scroll_offset < 0) ? 0 : scroll_offset;
            }
        }
    }

    // 键盘字符输入
    int key = GetCharPressed();
    while (key > 0)
    {
        if (key >= 32 && key <= 126 && strlen(input_str) < MAX_INPUT_LEN - 1)
        {
            memmove(&input_str[cursor + 1], &input_str[cursor], MAX_INPUT_LEN - cursor - 1);
            input_str[cursor++] = (char)key;
            filter_items();
        }
        key = GetCharPressed();
    }

    // 退格键
    if (IsKeyPressed(KEY_BACKSPACE) && cursor > 0)
    {
        cursor--;
        memmove(&input_str[cursor], &input_str[cursor + 1], MAX_INPUT_LEN - cursor - 1);
        filter_items();
    }

    // 方向键导航
    int center_pos = MAX_VISIBLE / 2;
    if ((IsKeyPressed(KEY_DOWN) || (ctrl_pressed && IsKeyPressed(KEY_N))) && selected_idx != -1)
    {
        int next_idx = selected_idx + 1;
        while (next_idx < item_count && !items[next_idx].is_match)
            next_idx++;
        if (next_idx < item_count)
        {
            selected_idx = next_idx;
            scroll_offset = selected_idx - center_pos;
            scroll_offset = (scroll_offset < 0) ? 0 : scroll_offset;
        }
    }

    if ((IsKeyPressed(KEY_UP) || (ctrl_pressed && IsKeyPressed(KEY_P))) && selected_idx != -1)
    {
        int prev_idx = selected_idx - 1;
        while (prev_idx >= 0 && !items[prev_idx].is_match)
            prev_idx--;
        if (prev_idx >= 0)
        {
            selected_idx = prev_idx;
            scroll_offset = selected_idx - center_pos;
            scroll_offset = (scroll_offset < 0) ? 0 : scroll_offset;
        }
    }

    // 光标导航
    if (IsKeyPressed(KEY_RIGHT) || (ctrl_pressed && IsKeyPressed(KEY_F)))
        cursor = (cursor < strlen(input_str)) ? cursor + 1 : cursor;
    if (IsKeyPressed(KEY_LEFT) || (ctrl_pressed && IsKeyPressed(KEY_B)))
        cursor = (cursor > 0) ? cursor - 1 : cursor;
    if (IsKeyPressed(KEY_HOME) || (ctrl_pressed && IsKeyPressed(KEY_A)))
        cursor = 0;
    if (IsKeyPressed(KEY_END) || (ctrl_pressed && IsKeyPressed(KEY_E)))
        cursor = strlen(input_str);

    // 删除键和Ctrl+K
    if ((IsKeyPressed(KEY_DELETE) || (ctrl_pressed && IsKeyPressed(KEY_D))) && cursor < strlen(input_str))
    {
        memmove(&input_str[cursor], &input_str[cursor + 1], MAX_INPUT_LEN - cursor - 1);
        filter_items();
    }

    if (ctrl_pressed && IsKeyPressed(KEY_K))
    {
        input_str[cursor] = '\0';
        filter_items();
    }

    // 执行命令
    if (IsKeyPressed(KEY_ENTER))
    {
        const char *cmd = NULL;
        if (selected_idx != -1 && items[selected_idx].is_match)
            cmd = items[selected_idx].text;
        else if (strlen(input_str) > 0)
            cmd = input_str;

        if (cmd)
            execute_command(cmd);
    }
}

// 渲染函数
void render_main_window()
{
    BeginDrawing();
    ClearBackground(BLACK);

    // 输入框
    DrawRectangle(PADDING, PADDING, WIDTH - 2 * PADDING, FONT_SIZE + 12, (Color){40, 40, 40, 255});

    // 提示文本
    const char *prompt_text = "Filter > ";
    DrawTextEx(app_font, prompt_text, (Vector2){PADDING + 8, PADDING + 6}, FONT_SIZE, 1, (Color){255, 255, 255, 255});
    float prompt_width = MeasureTextEx(app_font, prompt_text, FONT_SIZE, 1).x;

    // 用户输入文本
    DrawTextEx(app_font, input_str, (Vector2){PADDING + 8 + prompt_width, PADDING + 6}, FONT_SIZE, 1, (Color){255, 204, 0, 255});

    // 文本光标
    static double last_cursor_time = 0;
    static bool cursor_visible = true;
    double current_time = GetTime();
    if (current_time - last_cursor_time > 0.5)
    {
        cursor_visible = !cursor_visible;
        last_cursor_time = current_time;
    }
    if (cursor_visible && !command_executing)
    {
        char cursor_substr[MAX_INPUT_LEN];
        strncpy(cursor_substr, input_str, cursor);
        cursor_substr[cursor] = '\0';
        float cursor_x = prompt_width + PADDING + 8 + MeasureTextEx(app_font, cursor_substr, FONT_SIZE, 1).x;
        DrawRectangle(cursor_x, PADDING + 6, 2, FONT_SIZE, (Color){255, 255, 255, 255});
    }

    // 分隔线
    int separator_y = PADDING + FONT_SIZE + 20;
    DrawLine(PADDING, separator_y, WIDTH - PADDING, separator_y, (Color){80, 80, 80, 255});

    // 渲染过滤后的项目
    int y_offset = separator_y + 10;
    int visible_count = 0;
    int match_count = 0;

    for (int i = 0; i < item_count; i++)
        if (items[i].is_match)
            match_count++;

    for (int i = 0; i < item_count && visible_count < MAX_VISIBLE; i++)
    {
        if (items[i].is_match)
        {
            if (i < scroll_offset)
                continue;

            // 高亮选中项
            if (i == selected_idx)
                DrawRectangle(PADDING, y_offset - 2, WIDTH - 2 * PADDING, FONT_SIZE + 8, (Color){0, 102, 153, 204});

            // 绘制项目文本
            char display_text[256];
            strncpy(display_text, items[i].text, sizeof(display_text) - 1);
            display_text[sizeof(display_text) - 1] = '\0';
            DrawTextEx(app_font, display_text, (Vector2){PADDING + 10, y_offset}, FONT_SIZE, 1, (Color){255, 255, 255, 255});

            y_offset += FONT_SIZE + 12;
            visible_count++;
        }
    }

    // 状态提示
    if (command_executing)
    {
        const char *exec_hint = "Executing...";
        float hint_width = MeasureTextEx(app_font, exec_hint, 16, 1).x;
        DrawTextEx(app_font, exec_hint,
                   (Vector2){PADDING + hint_width, HEIGHT - PADDING - 20},
                   16, 1, (Color){255, 153, 0, 255});
    }
    else if (match_count > MAX_VISIBLE)
    {
        const char *scroll_hint = "PgUp/PgDn: Nav | Wheel: Scroll | Enter: Run | Esc: Quit";
        float hint_width = MeasureTextEx(app_font, scroll_hint, 16, 1).x;
        DrawTextEx(app_font, scroll_hint,
                   (Vector2){WIDTH - PADDING - hint_width - 5, HEIGHT - PADDING - 20},
                   16, 1, (Color){0, 204, 102, 255});
    }

    EndDrawing();
}

// 信号处理函数
void sigchld_handler(int signum)
{
    int status;
    while (waitpid(-1, &status, WNOHANG) > 0)
    {
        // leave it
    }
}

int main()
{
    // 设置SIGCHLD信号处理
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = sigchld_handler;
    sa.sa_flags = SA_RESTART;
    sigaction(SIGCHLD, &sa, NULL);

    // 初始化raylib
    SetTraceLogLevel(LOG_NONE);
    InitWindow(WIDTH, HEIGHT, "rmenu");
    SetTargetFPS(60);
    SetExitKey(0);

    // 字体加载（修复Font.id问题：移除id检查）
    default_font = GetFontDefault();
    app_font = LoadFont(SYSTEM_FONT_PATH);
    bool is_custom_font = false;
    if (app_font.baseSize == 0)
    {
        fprintf(stderr, "Warning: Using default font (system font load failed)\n");
        app_font = default_font;
    }
    else
    {
        is_custom_font = true; // 标记是否为自定义加载的字体
    }

    // 读取输入项目
    read_items_from_stdin();
    filter_items();

    // 主循环
    while (running && !WindowShouldClose())
    {
        // 检查子进程状态
        check_child_process();

        // 处理输入
        handle_input();

        // 渲染窗口
        render_main_window();

        // 命令执行完成后关闭窗口
        if (window_should_close)
        {
            running = false;
            break;
        }
    }

    // 资源清理（修复Font.id问题：根据标记释放自定义字体）
    if (is_custom_font)
    {
        UnloadFont(app_font);
    }

    // 回收子进程
    if (child_pid != -1)
    {
        int status;
        waitpid(child_pid, &status, WNOHANG);
    }

    CloseWindow();
    return 0;
}
